﻿using System;
using System.Collections.Generic;
using Crosland.Offline.Core;
using Crosland.Offline.Logic;
using Crosland.Framework.Base;

namespace Crosland.Offline.Logic
{
    public class SeguridadLogic
    {

        /// <summary>
        /// Valida si el usuario se encuentra registrado y tiene permisos
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="password"></param>
        /// <param name="empresaId"></param>
        /// <returns></returns>
        public string ValidarUsuario(string userName, string password)
        {
            Usuario usuario = Factory.GetUsuarioDao().GetById(userName);

            if (usuario != null)
            {
                if (usuario.IndEstado == Estados.Activo)
                {
                    if (password == Factory.GetUsuarioDao().DesEncriptarPassword(usuario.DesPassword))
                    {
                        return ResultadoLogin.LoginOk;
                    }
                    else
                    {
                        return ResultadoLogin.LoginPwdIncorrecto;
                    }
                }
                else
                {
                    return ResultadoLogin.LoginUserInactivo;
                }
            }
            else
            {
                return ResultadoLogin.LoginUserNoxiste;
            }
        }


        /// <summary>
        /// Permite encriptar el password del usuario
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public string EncriptarPassword(string password)
        {
            return Factory.GetUsuarioDao().EncriptarPassword(password);           
        }

        /// <summary>
        /// Permite encriptar el password del usuario
        /// </summary>
        /// <param name="password"></param>
        /// <returns></returns>
        public string DesEncriptarPassword(string password)
        {
            return Factory.GetUsuarioDao().DesEncriptarPassword(password);
        }

        /// <summary>
        /// Lista las opciones del sistema
        /// </summary>
        /// <returns></returns>
        public List<Opcion> ListarOpciones()
        {
            return Factory.GetOpcionDao().List();
        }

        /// <summary>
        /// Obtiene una opcione mediante el id
        /// </summary>
        /// <param name="idOpcion"></param>
        /// <returns></returns>
        public Opcion ObtenerOpcion(int idOpcion)
        {
            return Factory.GetOpcionDao().GetById(idOpcion);
        }

        /// <summary>
        /// Graba o actualiza una opcion del sistema
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public int GrabarOpcion(Opcion entity)
        {
            try
            {
                int resultado = 0;
                if (entity.ID == 0)
                {
                    resultado = Factory.GetOpcionDao().Save(entity);
                }
                else
                {
                    Factory.GetOpcionDao().Update(entity);
                    resultado = entity.ID;
                }
                return resultado;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Permite eliminar una opción
        /// </summary>
        /// <param name="idOpcion"></param>
        public void EliminarOpcion(int idOpcion)
        {
            try
            {
                Factory.GetOpcionDao().Delete(idOpcion);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Lista las opciones padre el usuario que ha iniciado sesion
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public List<Opcion> ListarOpcionPorPadre(string userName, int idPadre)
        {
            return Factory.GetOpcionDao().ObtenerPorUsuario(userName, idPadre);
        }


        /// <summary>
        /// Realiza una búsqueda de Grupos
        /// </summary>
        /// <param name="nombre"></param>
        /// <returns></returns>
        public List<Rol> BuscarGrupos(string nombre)
        {
            return Factory.GetRolDao().GetByCriteria(nombre);
        }

        /// <summary>
        /// Permite obtener los datos de un grupo
        /// </summary>
        /// <param name="idGrupo"></param>
        /// <returns></returns>
        public Rol ObtenerGrupo(int idGrupo)
        {
            return Factory.GetRolDao().GetById(idGrupo);
        }

        /// <summary>
        /// Cambia el estado de un grupo
        /// </summary>
        /// <param name="idGrupo"></param>
        public void EliminarGrupo(int idGrupo, string idUsuario)
        {
            try
            {
                Rol entity = Factory.GetRolDao().GetById(idGrupo);
                entity.IndEstado = Estados.Eliminado;
                Factory.GetRolDao().Update(entity);
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Permite grabar los datos del grupo y sus accesos
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="listOpciones"></param>
        /// <returns></returns>
        public int GrabarGrupo(Rol entity, List<int> listOpciones)
        {
            try
            {
                int id = 0;
                if (entity.ID == 0)
                {
                    id = Factory.GetRolDao().Save(entity);

                }
                else
                {
                    Factory.GetRolDao().Update(entity);
                    id = entity.ID;
                }
                this.GrabarAccesosGrupo(id, listOpciones);
                return id;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Permite grabar los accesos de un grupo
        /// </summary>
        /// <param name="id"></param>
        /// <param name="listOpciones"></param>
        protected void GrabarAccesosGrupo(int id, List<int> listOpciones)
        {
            Factory.GetRolDao().Delete(id);

            foreach (int idOpcion in listOpciones)
            {
                RolOpcion entity = new RolOpcion();
                entity.ID = new RolOpcion.RolOpcionID();
                entity.ID.IdRol = id;
                entity.ID.IdOpcion = idOpcion;

                Factory.GetRolOpcionDao().Save(entity);
            }
        }

        /// <summary>
        /// Permite obtener las opciones de cada grupo
        /// </summary>
        /// <param name="idGrupo"></param>
        public List<int> ObtenerOpcionesPorGrupo(int idGrupo)
        {
            List<int> list = new List<int>();
            List<Opcion> listOpcion = Factory.GetOpcionDao().GetByCriteria(idGrupo);

            foreach (Opcion item in listOpcion)
            {
                list.Add(item.ID);
            }

            return list;
        }


        /// <summary>
        /// Realiza una busqueda de usuarios
        /// </summary>
        /// <returns></returns>
        public List<Usuario> BuscarUsuarios(string nombre)
        {
            return Factory.GetUsuarioDao().GetByCriteria(nombre);
        }

        /// <summary>
        /// Obtiene los datos de un usuario
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public Usuario ObtenerUsuario(string userName)
        {
            return Factory.GetUsuarioDao().GetById(userName);
        }

        /// <summary>
        /// Valida si existe un usuario registrado con el mismo nombre de usuario
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        protected bool ValidarExistenciaUsuario(string userName)
        {
            Usuario usuario = Factory.GetUsuarioDao().GetById(userName);
            if (usuario != null)
            {
                if (!string.IsNullOrEmpty(usuario.ID))
                {
                    return true;
                }
            }
            return false;
        }

        /// <summary>
        /// Elimina los datos de un usuario
        /// </summary>
        public void EliminarUsuario(string userName, string idUsuario)
        {
            try
            {
                Usuario entity = Factory.GetUsuarioDao().GetById(userName);
                entity.IndEstado = Estados.Eliminado;

                Factory.GetUsuarioDao().Update(entity);

            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }

        }


        /// <summary>
        /// Permite realizar el cambio de usuario
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="pwdOld"></param>
        /// <param name="pwdNew"></param>
        /// <returns></returns>
        public string CambiarPasswordUsuario(string userName, string pwdOld, string pwdNew)
        {
            try
            {
                Usuario usuario = Factory.GetUsuarioDao().GetById(userName);

                if (pwdOld == Factory.GetUsuarioDao().DesEncriptarPassword(usuario.DesPassword))
                {
                    usuario.DesPassword = this.EncriptarPassword(pwdNew);
                    Factory.GetUsuarioDao().Update(usuario);
                    return ResultadoCambioPasssword.CambioOk;
                }
                else
                {
                    return ResultadoCambioPasssword.PasswordNoCoincide;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Permite recuperar el password del usuario
        /// </summary>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <returns></returns>
        public string RecuperarPassword(string email, out string password, out string nombre)
        {
            try
            {
                password = null;
                nombre = null;
                if (!string.IsNullOrEmpty(email))
                {

                    string id = Factory.GetUsuarioDao().ValidarEmail(email);
                    if (!string.IsNullOrEmpty(id))
                    {
                        Usuario usuario = Factory.GetUsuarioDao().GetById(id);

                        if (usuario != null)
                        {
                            password = Factory.GetUsuarioDao().DesEncriptarPassword(usuario.DesPassword);
                            nombre = usuario.DesNombre + " " + usuario.DesApellido;
                            return ResultadoRecuperarPwd.RecuperacionOK;
                        }
                        else
                        {
                            return ResultadoRecuperarPwd.RecuperacionError;
                        }
                    }
                    else
                    {
                        return ResultadoRecuperarPwd.EmailIncorrecto;
                    }
                }
                else
                {
                    return ResultadoRecuperarPwd.EmailRequerido;
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }


        /// <summary>
        /// Obtiene los grupos a los cuales pertenece un usuario
        /// </summary>
        /// <param name="userName"></param>
        /// <returns></returns>
        public List<UsuarioRol> ObtenerGruposPorUsuario(string userName)
        {
            return Factory.GetUsuarioRolDao().GetByCriteria(userName);
        }


        /// <summary>
        /// Permite grabar un nuevo usuario
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="indNuevo"></param>
        /// <param name="listGrupos"></param>
        public bool GrabarUsuario(Usuario entity, bool indNuevo, List<int> listGrupos)
        {
            try
            {
                bool flag = true;
                if (indNuevo)
                {
                    if (!this.ValidarExistenciaUsuario(entity.ID))
                    {
                        Factory.GetUsuarioDao().Save(entity);
                        flag = true;
                    }
                    else
                    {
                        flag = false;
                    }
                }
                else
                {
                    Factory.GetUsuarioDao().Update(entity);
                    flag = true;
                }
                if (flag)
                    this.GrabarGruposUsuario(entity.ID, listGrupos);

                return flag;
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message, ex);
            }
        }

        /// <summary>
        /// Graba los grupos a los cuales pertenece un usuario
        /// </summary>
        /// <param name="username"></param>
        /// <param name="listGrupo"></param>
        protected void GrabarGruposUsuario(string username, List<int> listGrupo)
        {
            Factory.GetUsuarioDao().Delete(username);
            foreach (int id in listGrupo)
            {
                UsuarioRol entity = new UsuarioRol();
                entity.ID = new UsuarioRol.UsuarioRolID();

                entity.ID.IdRol = id;
                entity.ID.IdUsuario = username;

                Factory.GetUsuarioRolDao().Save(entity);
            }
        }

        /// <summary>
        /// Permite obener el número de subnodos 
        /// </summary>
        /// <param name="idPadre"></param>
        /// <returns></returns>
        public int ObtenerNroElementosPorNodo(int? idPadre)
        {
            return Factory.GetOpcionDao().GetNroSubNodos(idPadre);
        }
    }
}
